package fitness;

import java.util.HashMap;

import common.Static;
import optimizers.ganeat.math.ConstantsMath;

public class MathResult extends FitnessResult {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public HashMap<String, Double> errors;
	public double target_max;

	public HashMap<String, Double> targets = new HashMap<String, Double>();
	public HashMap<String, Double> actuals = new HashMap<String, Double>();
	public double scale = 1;

	public double[] targetFittedParams;
	public double[] actualFittedParams;

	public boolean minFitness;

	@Override
	public Double[] getDecomposition() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public double finalResult() {
		if (minFitness)
			return 0;
		double result = 0;
		for (double error : errors.values()) {
			result += Math.pow(error, 2);// modified to square by YR
		}
		result = 10000 / Math.max(result, 0.01);
		if (targetFittedParams != null) {
			for (int i = 0; i < targetFittedParams.length; i++) {
				result = result
						* Math.exp(-(actualFittedParams[i] - targetFittedParams[i])
								* (actualFittedParams[i] - targetFittedParams[i])
								/ (targetFittedParams[i]
										* targetFittedParams[i] / 100));
			}
		}
		// return 1000 / result;
		// return Math.exp(-((double)1/square_a-50)*((double)1/square_a-50)/25)
		// * 1000 / result;

		// return Math.exp(-((double) gaussian_A - 50)
		// * ((double) gaussian_A - 50) / 25)
		// * Math.exp(-((double) gaussian_u - 100)
		// * ((double) gaussian_u - 100) / 100)
		// * Math.exp(-((double) gaussian_o - 20)
		// * ((double) gaussian_o - 20) / 4) * 1000000 * ConstantsMath.nTests /
		// result;
		return result;
	}

	@Override
	public String toString() {
		if (minFitness)
			return " = minFitness";
		StringBuilder builder = new StringBuilder();
		builder.append(Static.df4.format(finalResult()));
		builder.append("(scale=" + Static.df4.format(scale) + ")");

		builder.append("=10000/(");
		int i = 0;
		for (double error : errors.values()) {
			builder.append("("
					+ (error == Double.MAX_VALUE ? "MAX_VALUE" : Static.df4
							.format(error)) + ")^2 ");// mod YR
			i++;
			if (i < errors.size() - 1) {
				builder.append(" + ");
			}
		}
		builder.append(") ");
		if (targetFittedParams != null) {
			for (int j = 0; j < targetFittedParams.length; j++) {
				builder.append(actualFittedParams[j] + " ");
			}
		}
		return builder.toString();
	}

	@Override
	public boolean goodSolution() {
		for (double error : errors.values()) {
			if (Math.abs(error / target_max) > ConstantsMath.stoppingError) {
				return false;
			}
		}
		for (int i = 0; i < targetFittedParams.length; i++) {
			if (Math.abs(targetFittedParams[i] - actualFittedParams[i])
					/ targetFittedParams[i] > ConstantsMath.stoppingError) {
				return false;
			}
		}
		return true;
	}

}
